package com.woniu.zsd.platform.config;//package com.woniu.zsd.common.config;


import org.eclipse.paho.client.mqttv3.MqttConnectOptions;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.integration.annotation.ServiceActivator;
import org.springframework.integration.channel.DirectChannel;
import org.springframework.integration.core.MessageProducer;
import org.springframework.integration.mqtt.core.DefaultMqttPahoClientFactory;
import org.springframework.integration.mqtt.core.MqttPahoClientFactory;
import org.springframework.integration.mqtt.inbound.MqttPahoMessageDrivenChannelAdapter;
import org.springframework.integration.mqtt.outbound.MqttPahoMessageHandler;
import org.springframework.integration.mqtt.support.DefaultPahoMessageConverter;
import org.springframework.integration.mqtt.support.MqttHeaders;
import org.springframework.messaging.MessageChannel;
import org.springframework.messaging.MessageHandler;
import org.springframework.messaging.MessageHeaders;

import java.util.Objects;
import java.util.UUID;

@Configuration
public class MqttConfig {
    @Value("${iot.mqtt.serverURIs}")
    private String[] serverURIs;
    @Value("${iot.mqtt.defaultTopic}")
    private String defaultTopic;
    @Value("${iot.mqtt.clientId}")
    private String clientId;
    @Value("${iot.mqtt.receiveTopics}")
    private String[] receiveTopics;


    /**
     * MQTT连接配置 若要设置ssl验证也在这里设置
     * @return factory
     * MQTT 配置类，用于设置 MQTT 客户端的连接参数和 QoS 级别。
     * MQTT 协议定义了三种不同的 QoS 级别，用于描述消息的传输质量：
     * 1. QoS 0（At most once）：这是最低的 QoS 级别。在这种模式下，消息最多被发送一次，但没有确认机制。
     *     这意味着消息可能会丢失，但客户端不会收到重复的消息。
     * 2. QoS 1（At least once）：在这种 QoS 级别下，消息至少会被发送一次，并且客户端会接收到消息的确认。
     *     如果消息在传输过程中丢失，服务器会重新发送消息。因此，客户端可能会收到重复的消息。
     * 3. QoS 2（Exactly once）：这是最高的 QoS 级别。在这种模式下，消息只会被发送一次，并且客户端会接收到消息的确认。
     *     服务器确保消息只被处理一次，即使客户端可能因为网络问题而多次请求消息。
     */

    @Bean
    public MqttPahoClientFactory mqttClientFactory() {
        DefaultMqttPahoClientFactory factory = new DefaultMqttPahoClientFactory();
        MqttConnectOptions options = new MqttConnectOptions();
        options.setServerURIs(serverURIs);
        options.setCleanSession(false);      // 保留会话状态
        options.setAutomaticReconnect(true); // 开启自动重连
        options.setKeepAliveInterval(2);    // 心跳间隔（秒）
        options.setConnectionTimeout(30);    // 连接超时时间
        factory.setConnectionOptions(options);
        return factory;
    }

    /**
     * 消息入站通道 也可以作为出站通道
     */
    @Bean
    public MessageChannel mqttInputChannel() {
        return new DirectChannel();
    }
    /**
     * 消息入站
     */
    @Bean
    public MessageProducer inbound(){
        System.out.println("clientId: "+clientId);
        //paho客户端消息驱动通道适配器 用来订阅主题
        MqttPahoMessageDrivenChannelAdapter adapter = new MqttPahoMessageDrivenChannelAdapter(clientId, mqttClientFactory(),
                receiveTopics);
        adapter.setCompletionTimeout(5000);
        DefaultPahoMessageConverter converter = new DefaultPahoMessageConverter();
        //是否按字节接收消息
//        converter.setPayloadAsBytes(true);
        adapter.setConverter(converter);
        adapter.setQos(1);
        adapter.setOutputChannel(mqttInputChannel());
        return adapter;
    }

    @Bean
    // ServiceActivator注解表明：当前方法用于处理MQTT消息，inputChannel参数指定了用于消费消息的channel。
    @ServiceActivator(inputChannel = "mqttInputChannel")
    public MessageHandler handler() {
        return message -> {
            String payload = message.getPayload().toString();
            UUID uuid = message.getHeaders().getId();
            // byte[] bytes = (byte[]) message.getPayload(); // 收到的消息是字节格式
            MessageHeaders headers = message.getHeaders();
            String topic = Objects.requireNonNull(headers.get(MqttHeaders.RECEIVED_TOPIC)).toString();
            String receivedQOS = headers.get(MqttHeaders.RECEIVED_QOS).toString();
            // 根据主题分别进行消息处理。
            System.out.println("消息主题:"+topic);
            System.out.println("消息正文:"+payload);
        };
    }
    /**
     * 出站通道
     */
    @Bean
    public MessageChannel mqttOutboundChannel() {
        return new DirectChannel();
    }

    /**
     * 出站
     */
    @Bean
    @ServiceActivator(inputChannel = "mqttOutboundChannel")
    public MessageHandler outbound() {
        // 发送消息和消费消息Channel可以使用相同MqttPahoClientFactory
        MqttPahoMessageHandler messageHandler = new MqttPahoMessageHandler(clientId, mqttClientFactory());
        messageHandler.setAsync(true); // 如果设置成true，即异步，发送消息时将不会阻塞。
        messageHandler.setDefaultTopic(defaultTopic);
        messageHandler.setDefaultQos(2); // 设置默认QoS

        // Paho消息转换器
        DefaultPahoMessageConverter defaultPahoMessageConverter = new DefaultPahoMessageConverter();

        // defaultPahoMessageConverter.setPayloadAsBytes(true); // 发送默认按字节类型发送消息
        messageHandler.setConverter(defaultPahoMessageConverter);
        return messageHandler;
    }

}

